//
//  LBReactBridge.h
//  LBReact
//
//  Created by WuShiHai on 19/5/24.
//  Copyright (c) 2019 Lebbay. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "LBBridge.h"

#import "LBReactError.h"

typedef void (^LBReactBridgeRenderCompleteBlock)(BOOL isSuccess, NSError *error, BOOL isUpdate);
typedef void (^LBReactBridgeJSCallbackBlock)(void);
typedef void (^LBReactBridgeRenderMainBlock)(LBBridge *bridge, NSError *error);

UIKIT_EXTERN NSString *const LBJavaScriptDidLoadAppNotification;
UIKIT_EXTERN NSString *const LBJavaScriptDidLoadModuleNotification;

typedef NS_ENUM(NSInteger, LBReactBridgeMode) {
    LBReactBridgeServerMode = 0, //本地连接模式
    LBReactBridgeSingleMode = 1, //单包模式
    LBReactBridgeMultiMode = 2, //多包模式
};

typedef NS_ENUM(NSInteger, LBReactBridgeRenderState) {
    LBReactBridgeRenderStateUnKown = 0, //未开始加载
    LBReactBridgeRenderStateRendering = 1, //渲染中
    LBReactBridgeRenderStateSuccess = 2, //渲染成功
    LBReactBridgeRenderStateFail = 3, //渲染失败
    LBReactBridgeRenderStateJSCallback = 4, //JS 成功回调
};

typedef NS_ENUM(NSInteger, LBReactBridgeRenderLevel) {
    LBReactBridgeRenderEveryFetchLevel = 1, //每次都重新获取，加载失败后会加载本地的
    LBReactBridgeRenderPriorityLocalLevel = 2, //优先加载本地的，如果本地的没有，则会去接口下载
    LBReactBridgeRenderFetchInIntervalLevel = 3, //每隔默认的时间，当加载新页面，会重新获取
    LBReactBridgeRenderDefaultLevel = LBReactBridgeRenderEveryFetchLevel, //默认级别
};

#define LBReactBridgeManager [LBReactBridge manager]
#define LBReactBridgeManagerMode [LBReactBridge manager].mode

/**
 LBReactNative模块供外部调用的类，主要业务使用类
 */
@interface LBReactBridge : NSObject
    
/**
 单例

 @return 实例
 */
+ (instancetype)manager;

/**
 补丁包使用模式，单包 or 多包 or 开发
 */
@property (nonatomic, assign, readonly) LBReactBridgeMode mode;

/**
 当前展示的React-Native所使用的bridge, LBReactBridgeMultiMode下 为启动时候首次生成的bridge
 */
@property (nonatomic, strong, readonly) LBBridge *bridge;

/**
 主包路径
 */
@property (nonatomic, strong, readonly) NSURL *bundleURL;

/**
 jsbundle加载状态
 */
@property (nonatomic, assign, readonly) LBReactBridgeRenderState renderState;

/**
 js 加载完回调
 */
@property (nonatomic, strong, readonly) LBReactBridgeJSCallbackBlock callback;

/**
 js 渲染完回调
 */
@property (nonatomic, strong, readonly) LBReactBridgeJSCallbackBlock renderCallback;

/**
 js加载完异步信息后，回调，通知原生加载js页面

 @param callback 回调
 */
- (void)registerJSCallback:(LBReactBridgeJSCallbackBlock)callback;

/**
 js渲染完后，回调，通知原生关闭闪屏
 
 @param renderCallback 回调
 */
- (void)registerJSRenderCallback:(LBReactBridgeJSCallbackBlock)renderCallback;

/**
 加载JavaScript到内存中

 @param mode 补丁包加载模式
 @param bundlePath 根据bundlePath加载路径
 @param launchOptions 启动信息
 @param complete 完成回调
 */
- (void)render:(LBReactBridgeMode)mode
    bundlePath:(NSString *)bundlePath
 launchOptions:(NSDictionary *)launchOptions
      complete:(LBReactBridgeRenderCompleteBlock)complete;

/**
  加载JavaScript到内存中

 @param mode 补丁包加载模式
 @param isServer 是否本地开发模式下的bundle
 @param bundlePath 根据bundlePath加载路径
 @param bundleName 如果isServer=NO,bundlePath为空，则加载本地的资源，优先加载{{bundleName}}.jsbundle文件，默认加载index.ios.jsbundle
 @param launchOptions 启动信息
 @param complete 完成回调
 */
- (void)render:(LBReactBridgeMode)mode
    bundlePath:(NSString *)bundlePath
    bundleName:(NSString *)bundleName
 launchOptions:(NSDictionary *)launchOptions
      complete:(LBReactBridgeRenderCompleteBlock)complete;

/**
 执行代码段

 @param bridge 执行代码段的桥接
 @param folderPath 以jsbundled为后缀的文件所在的文件夹
 @param module 模块名称
 @param index 模块bundleId
 @param complete 完成回调
 */
- (void)executeSourceCodeIn:(LBBridge *)bridge 
                 folderPath:(NSString *)folderPath
                     module:(NSString *)module
                      index:(NSUInteger)index
                   complete:(LBReactBridgeRenderCompleteBlock)complete;

/**
 执行代码段
 
 @param bridge 执行代码段的桥接
 @param sourceCode 代码段
 @param module 模块名称
 @param index 模块版本号 bundleId
 @param folderPath 模块存放文件夹
 @param complete 完成回调
 */
- (void)executeSourceCodeIn:(LBBridge *)bridge
                 sourceCode:(NSData *)sourceCode
                     module:(NSString *)module
                      index:(NSUInteger)index
                 folderPath:(NSString *)folderPath
                   complete:(LBReactBridgeRenderCompleteBlock)complete;

/**
 执行代码段
 
 @param bridge 执行代码段的桥接
 @param sourceCode 代码段
 @param moduleInfos 模块信息数组
 @param module 模块名称
 @param complete 完成回调
 */
- (void)executeSourceCodeIn:(LBBridge *)bridge
                 sourceCode:(NSData *)sourceCode
                moduleInfos:(NSArray<LBBridgeModuleInfo *> *)moduleInfos
                     module:(NSString *)module
                   complete:(LBReactBridgeRenderCompleteBlock)complete;

/**
 根据给出的路径获取已经渲染该路径的bridge

 @param component 路径
 @return bridge实例
 */
- (LBBridge *)bridgeWithComponent:(NSString *)component;

/**
 获取一个渲染主包的bridge

 @param complete 完成回调
 */
- (void)fetchMainBrdige:(LBReactBridgeRenderMainBlock)complete;

/**
 增加bridge使用次数

 @param bridge bridge实例
 */
- (void)increase:(LBBridge *)bridge;

/**
 减少bridge使用次数，临时bridge使用次数为0，会进行释放

 @param bridge bridge实例
 */
- (void)decrease:(LBBridge *)bridge;

@end
